#ifndef _timberyard_db_h_
#define _timberyard_db_h_

#include <timberyard/utils.h>
#include <timberyard/threadpool.h>
#include <timberyard/exception.h>
#include <timberyard/queue.h>

#include <boost/thread/mutex.hpp>
#include <pqxx/transaction.hxx>
#include <pqxx/trigger.hxx>
#include <list>
#include <string>
#include <utility>
#include <tr1/functional>

extern "C" {
#include <time.h>
}

namespace Timberyard {

class DBTransaction;
namespace Internal {
class DBTrigger;
}

class DBPool :private Uncopyable {
	public:
		DBPool(const std::string& connection) : m_mutex(),m_free(),m_connection(connection),m_threadpool(),m_notif_con(),m_notif_queue() {};
		void BackgroundNotifications(ThreadPool* pool=0);
		void NotificationCallback(const std::string& name,std::tr1::function< void ()> fn);

	protected:
		pqxx::connection_base& Request();
		void Release(pqxx::connection_base& con);
		void Tidy(unsigned int maxage);
		pqxx::connection_base& GetNotifConnection();
		void NotifyHandlerThread();
		void NotifyHandler(std::tr1::function<void ()> fn);

		boost::mutex m_mutex;
		std::list<std::pair<pqxx::connection_base*,time_t> > m_free;
		std::string m_connection;
		friend class Timberyard::DBTransaction;
		friend class Timberyard::Internal::DBTrigger;

		ThreadPool* m_threadpool;
		pqxx::connection_base* m_notif_con;
		Queue<std::pair<std::string,std::tr1::function<void ()> > > m_notif_queue;
};

class DBTransaction : public pqxx::transaction<pqxx::read_committed> {
	public:
		DBTransaction(DBPool& pool, const std::string& name);
		DBTransaction(DBPool& pool);
		virtual ~DBTransaction() throw ();
	protected:
		DBPool& m_pool;
};

}

#endif // _timberyard_db_h_
